/**
 * Copyright (c) 2010-2011 julewa.com.  
 * All rights reserved. 
 * 
 * @author Huang Benhua
 * @date 2011-2-20
 * 
**/
package com.julewa.db.ibatis;

import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.julewa.db.BeanInfo;
import com.julewa.db.DB;
import com.julewa.loading.SpringLoader;

@SuppressWarnings("rawtypes")
public final class IbatisDB implements DB{
	private @Autowired Ibatis ibatis;
	private SqlMapClient sqlMap = null;
	public IbatisDB(){}
	
	@SuppressWarnings("unused")
	@PostConstruct
	private void init(){
		sqlMap = ibatis.getSqlMap();
		this.setBeans(ibatis.getBeans());
	}
	
	public boolean delete(String id, Object param) {
		try {
			this.sqlMap.delete(id, param);
			return true;
		} catch (SQLException e) {
			//throw new RuntimeException("[iBatis.delete]" + id, e);
			e.printStackTrace();
			return false;
		}
	}
	
	public int executeBatch() {
		try {
			return this.sqlMap.executeBatch();
		} catch (SQLException e) {
			throw new RuntimeException("[iBatis.batch.execute]", e);
		}
	}
	public boolean insert(String id, Object param) {
		try {
			this.sqlMap.insert(id, param);
			return true;
		} catch (SQLException e) {
			//throw new RuntimeException("[iBatis.insert]" + id, e);
			e.printStackTrace();
			return false;
		}
	}
	public List getList(String id, Object param) {
		try {
			return this.sqlMap.queryForList(id, param);
		} catch (SQLException e) {
			throw new RuntimeException("[iBatis.select]" + id, e);
		}
	}
	public List getList(String id, Object param, int skip, int max) {
		try {
			return this.sqlMap.queryForList(id, param, skip, max);
		} catch (SQLException e) {
			throw new RuntimeException("[iBatis.select]" + id, e);
		}
	}
	public Object getObject(String id, Object param) {
		try {
			return this.sqlMap.queryForObject(id, param);
		} catch (SQLException e) {
			throw new RuntimeException("[iBatis.select]" + id, e);
		}
	}
	public Object getObject(String id, Object param, Object resultObject) {
		try {
			return this.sqlMap.queryForObject(id, param, resultObject);
		} catch (SQLException e) {
			throw new RuntimeException("[iBatis.select]" + id, e);
		}
	}
	public void startBatch() {
		try {
			this.sqlMap.startBatch();
		} catch (SQLException e) {
			throw new RuntimeException("[iBatis.batch.start]", e);
		}
	}
	public boolean update(String id, Object param) {
		try {
			this.sqlMap.update(id, param);
			return true;
		} catch (SQLException e) {
			//throw new RuntimeException("[iBatis.update]" + id, e);
			e.printStackTrace();
			return false;
		}
	}
	
	public Map getMap(String id, Object param, String key) {
		try {
			return this.sqlMap.queryForMap(id, param, key);
		} catch (SQLException e) {
			throw new RuntimeException("[iBatis.select.map]" + id, e);
		}
	}
	
	@SuppressWarnings("unused")
	@Autowired(required=false)
	private void setIbatisLoader(IbatisTestLoader loader){
		this.sqlMap = loader.getSqlMapClient();
	}
	//
	private Map<String, BeanInfo> beans = null;
	private Set<Class<?>> autowireBeans = new HashSet<Class<?>>();
	public <T> T create(Class<T> clazz){
		if(autowireBeans.contains(clazz)){
			return SpringLoader.getInstance(clazz);
		}else{
			try {
				return clazz.newInstance();
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
		}
	};
	public Object create(String type){
		BeanInfo b = beans.get(type);
		if(b == null)return null;
		return SpringLoader.getInstance(b.getTypeClass());
	};
	void setBeans(Map<String, BeanInfo> vbeans){
		this.beans = Collections.synchronizedMap(new HashMap<String, BeanInfo>());
		for(BeanInfo b: vbeans.values()){
			this.beans.put(b.getTypeClass().getName(), b);
			this.beans.put(b.getCode(), b);
			if(b.isAutowire()) autowireBeans.add(b.getTypeClass());
		}
	}
	@Override
	public BeanInfo getBeanInfo(String type) {
		return beans.get(type);
	}

	public BeanInfo getBeanInfo(Class<?> type){
		return beans.get(type.getName());
	}
	
	//TODO 这里没有做任何国际化处理
	private Map<String, String> columnLabels = new HashMap<String, String>();
	public String findColumnLabel(String column){
		return columnLabels.get(column);
	};
	public String findColumnLabel(String prefix, String column){
		String l = findColumnLabel(prefix + "." + column);
		if(l != null)return l;
		return findColumnLabel(column);
	};
}
